#include <stdio.h>
#include <math.h>

#include "transf2d.h"

#define BUFSIZE 64

double Deg2Rad(int deg)
{
    return M_PI / 180 * deg;
}

void InitTranslat(Mat3x3 *m, int tx, int ty)
{
    m->elem[0][0] = 1;
    m->elem[0][1] = 0;
    m->elem[0][2] = tx;

    m->elem[1][0] = 0;
    m->elem[1][1] = 1;
    m->elem[1][2] = ty;

    m->elem[2][0] = 0;
    m->elem[2][1] = 0;
    m->elem[2][2] = 1;
}

void InitRot(Mat3x3 *m, int angle)
{
    double t = Deg2Rad(angle);

    m->elem[0][0] = cos(t);
    m->elem[0][1] = -sin(t);
    m->elem[0][2] = 0;

    m->elem[1][0] = sin(t);
    m->elem[1][1] = cos(t);
    m->elem[1][2] = 0;

    m->elem[2][0] = 0;
    m->elem[2][1] = 0;
    m->elem[2][2] = 1;
}

void InitScale(Mat3x3 *m, double sx, double sy)
{
    m->elem[0][0] = sx;
    m->elem[0][1] = 0;
    m->elem[0][2] = 0;

    m->elem[1][0] = 0;
    m->elem[1][1] = sy;
    m->elem[1][2] = 0;

    m->elem[2][0] = 0;
    m->elem[2][1] = 0;
    m->elem[2][2] = 1;
}

void InitRotPoint(Mat3x3 *m, int px, int py, int angle)
{
    Mat3x3 a, b, c;

    InitTranslat(&a, px, py);
    InitRot(&b, angle);
    InitTranslat(&c, -px, -py);

    matrix_mult(&a, &a, &b);
    matrix_mult(&a, &a, &c);

    *m = a;

    return;
}

void InitScalePoint(Mat3x3 *m, int px, int py, double sx, double sy)
{
    Mat3x3 a, b, c;

    InitTranslat(&a, px, py);
    InitScale(&b, sx, sy);
    InitTranslat(&c, -px, -py);

    matrix_mult(&a, &a, &b);
    matrix_mult(&a, &a, &c);

    *m = a;

    return;
}

void matrix_display(Mat3x3 *m)
{
    if (m == NULL)
    {
        printf("Matrix is null.\n");
        return;
    }

    int i, j;

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
            printf("%6.2lf ", m->elem[i][j]);
        printf("\n");
    }
}

void matrix_mult(Mat3x3 *r, Mat3x3 *a, Mat3x3 *b)
{
    Mat3x3 tmp;
    double sop;
    int i, j, k;

    for (i = 0; i < 3; i++)
    {
        for (k = 0; k < 3; k++)
        {
            sop = 0;

            for (j = 0; j < 3; j++)
                sop += a->elem[i][j] * b->elem[j][k];

            tmp.elem[i][k] = sop;
        }
    }

    *r = tmp;
    return;
}

int read_tsf(char *fileName, Mat3x3 *m)
{
    FILE *f_in;
    f_in = fopen(fileName, "rt");
    if (f_in == NULL) return -1;

    char buff[BUFSIZE];

    Mat3x3 a;
    int x, y, angle;
    double sx, sy;
    InitTranslat(m, 0, 0); //matricea identitate

    while (!feof(f_in))
    {
        fgets(buff, BUFSIZE, f_in);

        if (!feof(f_in))
        {
            switch (buff[0])
            {
                //translatie
            case 't' :
                sscanf(buff, "t %d %d", &x, &y);
                InitTranslat(&a, x, y);
                break;
                //scalare
            case 's' :
                sscanf(buff, "s %d %d %lf %lf", &x, &y, &sx, &sy);
                InitScalePoint(&a, x, y, sx, sy);
                break;
                //rotatie
            case 'r' :
                sscanf(buff, "r %d %d %d", &x, &y, &angle);
                InitRotPoint(&a, x, y, angle);
                break;
            default:
                break;
            }

            matrix_mult(m, &a, m);
        }
    }

    fclose(f_in);
    return 0;
}
